package com.jia.area.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jia.area.constant.AreaRedisConstant;
import com.jia.area.service.AreaShopService;
import com.jia.constant.RedisConstant;
import com.jia.shop.constant.ShopRedisConstant;
import com.jia.shop.entity.Shop;
import com.jia.shop.service.ShopService;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author jia
 */
@Service("areaShopService")
public class AreaShopServiceImpl implements AreaShopService {

    @Resource
    private ShopService shopService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    public static final String GEO_REDIS_PREFIX = RedisConstant.PROJECT_REDIS_PREFIX +
            ShopRedisConstant.SHOP_PREFIX +
            AreaRedisConstant.GEO_PREFIX;

    @Override
    public List<Shop> distanceShopList(Long shopTypeId, Integer current, Long distance,
                                       Double longitude, Double latitude) {
        QueryWrapper<Shop> wrapper = new QueryWrapper<>();
        wrapper.eq("type_id", shopTypeId);
        // 如果没有经纬度
        if (longitude == null || latitude == null) {
            Page selectPage = this.shopService.getBaseMapper().selectPage(new Page<>(current, 5), wrapper);
            return selectPage.getRecords();
        }
        int from = (current - 1) * 5;
        int end = current * 5;

        // 查询redis 按照距离排序 分页 结果 是 shopId，distance
        String key = GEO_REDIS_PREFIX + shopTypeId;

        GeoResults<RedisGeoCommands.GeoLocation<String>> results = stringRedisTemplate.opsForGeo()
//                .search()
                .radius(key, new Circle(new Point(longitude, latitude), distance),
                        RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                                .includeDistance().limit(end));

        if (results == null) {
            return Collections.emptyList();
        }
        List<GeoResult<RedisGeoCommands.GeoLocation<String>>> content = results.getContent();
        if (content.size() <= from) {
            return Collections.emptyList();
        }
        // 放置map
        Map<String, Object> map = new HashMap<>(content.size());
        content.stream().skip(from).forEach(result -> {
            String shopId = result.getContent().getName();
            Distance actualDistance = result.getDistance();
            map.put(shopId, actualDistance);
        });
        Set<String> shopIds = map.keySet();
        // 查询 shop 表
        String idsStr = StrUtil.join(",", shopIds);
        List<Shop> list = shopService.query().in("id", shopIds)
                .last("ORDER BY FIELD(id," + idsStr + ")").list();
        for (Shop shop : list) {
            Distance actualDistance = (Distance) map.get(shop.getId().toString());
            shop.setActualDistance(actualDistance.getValue());
        }
        return list;
    }
}
